/******************************************************************************
 * Copyright (C) 2017 Chengdu Dlhd information industry co. LTD.
 * All Rights Reserved.
 * 本软件为成都顶联互动信息产业有限公司开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、复制、修改或发布本软件.
 *****************************************************************************/
package net.dgg.dggcloud.service.iboss.service.sc;

import net.dgg.dggcloud.core.util.NJCodeUtil;
import net.dgg.dggcloud.service.common.base.SessionManager;
import net.dgg.dggcloud.service.common.base.service.BaseService;
import net.dgg.dggcloud.service.common.exception.BizException;
import net.dgg.dggcloud.service.dao.user.UserDao;
import net.dgg.dggcloud.service.entity.org.OrganizationEntity;
import net.dgg.dggcloud.service.entity.user.User;
import net.dgg.dggcloud.service.iboss.common.MapUtils;
import net.dgg.dggcloud.service.iboss.constant.*;
import net.dgg.dggcloud.service.iboss.dao.sc.ScOrderDao;
import net.dgg.dggcloud.service.iboss.dao.sc.ScProOrderDao;
import net.dgg.dggcloud.service.iboss.dao.sc.UserReadDao;
import net.dgg.dggcloud.service.iboss.entity.*;
import net.dgg.dggcloud.service.iboss.service.common.ChargeBackService;
import net.dgg.dggcloud.service.iboss.utils.DataWrap;
import net.dgg.dggcloud.service.jrcrm.entity.cms.MessageTemplate;
import net.dgg.dggcloud.service.jrcrm.entity.pro.Product;
import net.dgg.dggcloud.service.jrcrm.service.cms.BillNumberRuleService;
import net.dgg.dggcloud.service.jrcrm.service.cms.CustomerRecordService;
import net.dgg.dggcloud.service.jrcrm.service.cms.MessageService;
import net.dgg.dggcloud.service.jrcrm.service.cms.MessageTemplateService;
import net.dgg.dggcloud.service.jrcrm.service.orf.api.OrderApiService;
import net.dgg.dggcloud.service.jrcrm.utils.SmsBaiwu;
import net.dgg.dggcloud.service.service.organization.OrganizationService;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;


/**
 * @author 代杨
 * @ClassName ScProOrderService
 * @despriction 生产订单service
 * @create 2017/12/4 20:10
 **/
@Service
public class ScProOrderService extends BaseService {
    @Autowired
    private ScOrderDao scOrderDao;
    @Autowired
    private ScProOrderDao scProOrderDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private BillNumberRuleService billNumberRuleService;
    @Autowired
    private UserReadDao userReadDao;
    @Autowired
    private AbolishService abolishService;
    @Autowired
    private ScProOrderTimeStateService scProOrderTimeStateService;
    @Autowired
    private NodeManagerService nodeManagerService;
    @Autowired
    private ChargeBackService chargeBackService;
    @Resource
    protected MessageService messageService;
    @Resource
    protected OrderApiService orderApiService;
    @Resource
    protected CustomerRecordService customerRecordService;
    @Autowired
    private AllProOrderService allProOrderService;
    @Autowired
    private MessageTemplateService messageTemplateDao;
    @Resource
    private NJCodeUtil nJCodeUtil;
    @Autowired
    private WaitAllocationService waitAllocationService;

    private SmsBaiwu smaBaiwu = new SmsBaiwu();

    /**
     * 创建生产订单与子订单
     *
     * @param scOrder        生产主订单map
     * @param scProOrderList 生产子订单map集合
     */
    public void saveScOrderAndScProOrder(Map scOrder, List<Map> scProOrderList) {
        if (null == scOrder) {
            throw new BizException("生产主订单不能为空！", 10005);
        }
        if (null == scProOrderList || scProOrderList.size() == 0) {
            throw new BizException("生产子订单不能为空！", 10005);
        }

        ScOrder sc = null;
        List<ScProOrder> scProOrders = new ArrayList<>();
        try {
            sc = (ScOrder) MapUtils.convertJsonMap(ScOrder.class, scOrder);
            for (Map t : scProOrderList) {
                ScProOrder spo = (ScProOrder) MapUtils.convertJsonMap(ScProOrder.class, t);
                scProOrders.add(spo);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("转换为生产订单出现异常！" + e.getMessage(), 10005);
        }

        User singnUser = sc.getBusinessUserId() == null ? null : this.repository.get(User.class, sc.getBusinessUserId());  // 签单人信息
        OrganizationEntity org = singnUser == null || singnUser.getOrgId() == null ? null : this.repository.get(OrganizationEntity.class, singnUser.getOrgId());
        sc.setOrganizationName(org == null ? null : org.getName()); // 部门

        Date createDate = new Date();
        sc.setCreateTime(createDate);
        sc.setProOrderNo(this.billNumberRuleService.updateBillNumberByCode(OrderNoConstant.NO_CODE));
        sc.setId(this.keyWorker.nextId());
        //加密联系人电话
        //sc.setContactPhone(StringUtils.isEmpty(sc.getContactPhone()) ? sc.getContactPhone() : nJCodeUtil.encrypt(sc.getContactPhone()));
        this.repository.save(sc);

        Integer isbelongrisk = 2;//是否包含风控产品
        for (ScProOrder spo : scProOrders) {
            if (!StringUtils.isEmpty(spo.getBtCode()) && spo.getBtCode().contains(BusCodeConstant.BUS_YT_ZJYW)) {
                isbelongrisk = 1;
                break;
            }
        }

        for (int i = 0, len = scProOrders.size(); i < len; i++) {
            ScProOrder spo = scProOrders.get(i);
            spo.setSigningUserId(sc.getBusinessUserId()); // 签单人信息
            spo.setSigningUserName(String.format("%s%s", singnUser == null ? "" : singnUser.getName(), org == null ? "" : "(" + org.getName() + ")"));
            spo.setSigningDeptId(sc.getOrganizationId()); // 签单人部门
            spo.setSigningDeptName(org == null ? null : org.getName());
            User flowUser = null;
            if (spo.getFlowUserId() != null) {
                flowUser = spo.getFlowUserId() == null ? null : this.repository.get(User.class, spo.getFlowUserId()); // 流程人员
                OrganizationEntity flowOrg = flowUser == null || flowUser.getOrgId() == null ? null : this.repository.get(OrganizationEntity.class, flowUser.getOrgId());
                spo.setFlowUserName(String.format("%s%s", flowUser == null ? "" : flowUser.getName(), flowOrg == null ? "" : "(" + flowOrg.getName() + ")"));
                spo.setFlowDeptId(flowUser == null ? null : flowUser.getOrgId());
                spo.setFlowDeptName(flowOrg == null ? null : flowOrg.getName());

            }
            if (spo.getOrganizationId() != null) {
                OrganizationEntity flowBigOrg = this.repository.get(OrganizationEntity.class, spo.getOrganizationId());
                spo.setOrganizationName(flowBigOrg == null ? null : flowBigOrg.getName());
            }

            spo.setIsbelongrisk(isbelongrisk); //是否包含风控产品
            spo.setProOrderId(sc.getId()); // 生产主订单id
            spo.setProOrderNo(sc.getProOrderNo());// 生产主订单编号
            spo.setCustomerPhone(sc.getContactPhone()); //客户电话
            spo.setCustomerPhoneBak(nJCodeUtil.decrypt(sc.getContactPhone())); //客户电话明文
            spo.setBusinessId(sc.getBusinessId()); //商机
            spo.setBusinessNo(sc.getBusinessNo()); //
            spo.setMortgageAddress(sc.getMortgageAddress()); //抵押地址
            spo.setOrderBusinessNo(this.billNumberRuleService.updateBillNumberByCode(OrderNoConstant.NO_CODE));  // 生产子订单子订单编号
            spo.setPlaceOrderTime(sc.getPlaceOrderTime()); // 签单时间
            this.setScOrderStatus(spo); // 设置生产订单状态
            spo.setId(this.keyWorker.nextId());

            spo.setCreateTime(createDate);

            this.repository.save(spo);
            String[] vals = new String[1];
            vals[0] = String.valueOf(spo.getOrderBusinessNo());
            String tempCode = MsgCodeConstant.SC_DJS_MSG;
            //String tem = "订单{0}需要接收，请及时查看";
            if (flowUser != null && ScStatusConstant.RECEIVE_WAITING.equals(spo.getStatus())) {
                messageService.sendMessageReady(flowUser, singnUser, vals, tempCode);//消息提醒
                //发送短信给流程
                this.sendSmsMsgToUser(spo.getFlowUserId(), tempCode, spo.getOrderBusinessNo());
            }
        }

    }

    /**
     * 通过销售订单id 查询
     *
     * @param orderId
     * @return
     */
    public List<Map> listByOrderId(Long orderId) {
        if (orderId == null) {
            throw new BizException("销售订单ID不能为空！", 10005);
        }
        Map<String, Object> pMap = new HashMap<>();
        pMap.put("orderId", String.valueOf(orderId));
        return this.scProOrderDao.list(pMap);
    }

    /**
     * 通过销售订单编号 查询
     *
     * @param orderNo
     * @return
     */
    public List<Map> listByOrderNo(String orderNo) {
        if (StringUtils.isEmpty(orderNo)) {
            throw new BizException("销售订单ID不能为空！", 10005);
        }
        Map<String, Object> pMap = new HashMap<>();
        pMap.put("orderNo", orderNo);
        return this.scProOrderDao.list(pMap);
    }

    /**
     * 通过生产主订单id 查询
     *
     * @param proOrderId
     * @return
     */
    public List<Map> listByProOrderId(Long proOrderId) {
        if (proOrderId == null) {
            throw new BizException("销售订单ID不能为空！", 10005);
        }
        Map<String, Object> pMap = new HashMap<>();
        pMap.put("proOrderId", String.valueOf(proOrderId));
        return this.scProOrderDao.list(pMap);
    }

    /**
     * 通过生产主订单编号 查询
     *
     * @param proOrderNo
     * @return
     */
    public List<Map> listByProOrderNo(String proOrderNo) {
        if (StringUtils.isEmpty(proOrderNo)) {
            throw new BizException("销售订单编号不能为空！", 10005);
        }
        Map<String, Object> pMap = new HashMap<>();
        pMap.put("proOrderNo", proOrderNo);
        return this.scProOrderDao.list(pMap);
    }

    /**
     * 商机ID
     *
     * @param businessId
     * @return
     */
    public List<Map> listByBusinessId(Long businessId) {
        if (businessId == null) {
            throw new BizException("商机ID不能为空！", 10005);
        }
        Map<String, Object> pMap = new HashMap<>();
        pMap.put("businessId", String.valueOf(businessId));
        return this.scProOrderDao.list(pMap);
    }

    /**
     * 商机编号
     *
     * @param businessNo
     * @return
     */
    public List<Map> listByBusinessNo(String businessNo) {
        if (StringUtils.isEmpty(businessNo)) {
            throw new BizException("商机编号不能为空！", 10005);
        }
        Map<String, Object> pMap = new HashMap<>();
        pMap.put("businessNo", businessNo);
        return this.scProOrderDao.list(pMap);
    }


    /**
     * 批量查询
     *
     * @param map
     * @return
     */
    public List<Map> list(Map map) {
        return this.scProOrderDao.list(map);
    }

    /**
     * 统计
     *
     * @param map
     * @return
     */
    public Integer count(Map map) {
        return this.scProOrderDao.count(map);
    }

    /**
     * 根据ID查询
     *
     * @param scProOrderId
     * @return
     */
    public ScProOrder getById(Long scProOrderId) {
        return this.repository.get(ScProOrder.class, scProOrderId);
    }


    /**
     * 接收订单
     *
     * @param ids
     * @param channelId
     * @param productId
     * @param subBranch
     */
    public void update_receiveScproOrder(String ids, Long channelId, Long productId, String subBranch) {
        Assert.hasText(ids, "订单ID不能为空！");
        User user = SessionManager.getCurrentUser();
        Assert.notNull(user, "当前用户获取失败，请刷新重新登录！");

        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.replaceAll(" ", "").split(",");
        for (String t : idArr) {
            idList.add(Long.valueOf(t));
        }
        Assert.isTrue(idList.size() > 0, "订单ID数据错误");
        if (idList.size() == 1) {
            Assert.notNull(channelId, "渠道不能为空！");
            Assert.notNull(productId, "产品不能为空！");
        }

        OrganizationEntity org = user.getOrgId() == null ? null : this.repository.get(OrganizationEntity.class, user.getOrgId());

        Long bigOrgId = this.organizationService.getOrganizationDepartmentId(user.getOrgId()); //事业部ID
        OrganizationEntity bigOrg = this.repository.get(OrganizationEntity.class, bigOrgId);
        Set<String> receiveStatus = new HashSet<>(); //待接收
        receiveStatus.add(ScStatusConstant.RECEIVE_WAITING);
        receiveStatus.add(ScStatusConstant.SWITCH_WAITING);
        receiveStatus.add(ScStatusConstant.SWITCH_REFUSE);

        for (Long id : idList) {
            ScProOrder scProOrder = this.getById(id);
            if (scProOrder == null) {
                continue;
            }
            Assert.isTrue(receiveStatus.contains(scProOrder.getStatus()), String.format("编号为%s的订单的状态不能进行此操作！", scProOrder.getOrderBusinessNo()));
            if (ScStatusConstant.RECEIVE_WAITING.equals(scProOrder.getStatus()) || ScStatusConstant.SWITCH_REFUSE.equals(scProOrder.getStatus())) {
                // 下单代收和转单退回  接收时验证流程人员
                Assert.isTrue(scProOrder.getFlowUserId().equals(user.getId()), String.format("编号为%s的订单流程人员非当前登陆人，无法进行操作！", scProOrder.getOrderBusinessNo()));
            }
            if (ScStatusConstant.SWITCH_WAITING.equals(scProOrder.getStatus())) {
                // 转单代收 接收时验证接收人员
                Assert.isTrue(scProOrder.getWaitingReceiverId().equals(user.getId()), String.format("编号为%s的订单待接收人员非当前登陆人，无法进行操作！", scProOrder.getOrderBusinessNo()));
            }
            scProOrder.setOriginCode(ScStatusConstant.SWITCH_WAITING.equals(scProOrder.getStatus()) ? OriginCodeSource.SC_ORIGINCODE_RETUEN : OriginCodeSource.SC_ORIGINCODE_BUSINESS); // 订单来源
            scProOrder.setStatus(ScStatusConstant.ORDER_PROCESS); // SCORDER_STATUS02 //办理中
            scProOrder.setFlowUserId(user.getId()); //流程人员
            scProOrder.setFlowUserName(String.format("%s%s", user.getName(), org == null ? "" : "(" + org.getName() + ")"));
            scProOrder.setFlowDeptId(user.getOrgId());
            scProOrder.setFlowDeptName(org == null ? null : org.getName());
            scProOrder.setChannelId(channelId == null ? scProOrder.getChannelId() : channelId); //渠道
            scProOrder.setProductId(productId == null ? scProOrder.getProductId() : productId);//产品

            Product product = scProOrder.getProductId() == null ? null : this.repository.get(Product.class, scProOrder.getProductId());
            Assert.notNull(product, "未查询到产品，请刷新页面！");
            Assert.hasText(product.getType(), "产品的业态编码不能为空！");
            scProOrder.setBtCode(product.getType()); //根据产品设置业态码

            // 设置子订单及其他子订单是否含有资金业务
            Integer isbelongrisk = scProOrder.getBtCode().contains(BusCodeConstant.BUS_YT_ZJYW) ? 1 : this.getIsbelongrisk(scProOrder.getProOrderId(), scProOrder.getId());
            scProOrder.setIsbelongrisk(isbelongrisk);
            this.updateIsbelongrisk(scProOrder.getProOrderId(), isbelongrisk, scProOrder.getId());

            scProOrder.setSubBranch(StringUtils.isEmpty(subBranch) ? scProOrder.getSubBranch() : subBranch); //支行

            DataWrap.updateWraps(scProOrder); //更新操作人信息

            //操作记录
            ScProFlowOperating scProFlowOperating = new ScProFlowOperating();
            scProFlowOperating.setOperationType(ScOperationConstant.OPERATION_ORDER_RECEIVE); // SCORDER_CZ_CODE2 接收
            scProFlowOperating.setProProductId(scProOrder.getId());
            scProFlowOperating.setProProductNo(scProOrder.getOrderBusinessNo());
            scProFlowOperating.setFlowUserId(scProOrder.getFlowUserId());
            scProFlowOperating.setFlowUserName(scProOrder.getFlowUserName());
            scProFlowOperating.setStatus(scProOrder.getStatus());
            scProFlowOperating.setOperation("接收订单");
            DataWrap.saveWrap(scProFlowOperating);
            scProFlowOperating.setId(this.keyWorker.nextId());
            this.repository.save(scProFlowOperating);
            scProOrder.setFlowLatestOperationId(scProFlowOperating.getId()); //设置当前记录

            //非新增渠道子订单 同步状态数据
            if (scProOrder.getOrderId() != null && scProOrder.getOrderBusId() != null) {
                Map<String, Object> pMap = new HashMap<>();
                pMap.put("mainOrderId", String.valueOf(scProOrder.getOrderId()));
                pMap.put("childOrderId", String.valueOf(scProOrder.getOrderBusId()));
                pMap.put("orderStatus", OrderSyncStatusConstant.ORF_BDZT_5); // ORF_BDZT_5
                this.orderApiService.synOrderState(pMap);
            }
            //同步备注到crm
            Map recordMap = new HashMap();
            recordMap.put("tableName", ScProOrder.TABLE_NAME);
            recordMap.put("tableId", scProOrder.getId());
            recordMap.put("cusId", scProOrder.getCustomerId());
            recordMap.put("recordType", RemarkOperationConstant.REMARK_ORDER_RECEIVE);//备注类型
            recordMap.put("content", "接收订单");//备注内容
            recordMap.put("operateUser", user.getId());//当前操作人id
            recordMap.put("ext3", scProOrder.getOrderBusinessNo()); //生产子订单编号
            customerRecordService.saveCustomerRecord(recordMap);//写入crm

            ScProOrderTimeState state = this.repository.get(ScProOrderTimeState.class, scProOrder.getId());
            if (state == null) {  //通过超时记录判断 是否 接收过
                scProOrder.setOrderTime(new Date()); //接单时间
                Map map = this.scProOrderTimeStateService.addScProOrderTimeState(scProOrder); //创建超时状态数据
                try {
                    this.allProOrderService.saveUpdateNodeInfo(map, user);
                } catch (Exception e) {
                    String msg = e.getMessage();
                    Assert.isTrue(false, StringUtils.isEmpty(msg) ? "系统出现异常！" : msg);
                }
            }


        }

    }

    /**
     * 更换渠道
     *
     * @param ids
     * @param productId
     * @param channelId
     * @param subBranch
     */
    public void update_changeChannel(String ids, Long channelId, String subBranch) {
        Assert.hasText(ids, "订单ID不能为空！");
        User user = SessionManager.getCurrentUser();
        Assert.notNull(user, "当前用户获取失败，请刷新重新登录！");

        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.replaceAll(" ", "").split(",");
        for (String t : idArr) {
            idList.add(Long.valueOf(t));
        }
        Assert.isTrue(idList.size() > 0, "订单ID数据错误");
//        Assert.notNull(productId, "产品不能为空！");
        Assert.notNull(channelId, "渠道不能为空！");

//        Product product = this.repository.get(Product.class, productId);
//        Assert.notNull(product, "未查询到产品,请刷新后重试！");

        Set<String> receiveStatus = new HashSet<>(); //办理中。已暂缓暂缓
        receiveStatus.add(ScStatusConstant.ORDER_PROCESS);
        receiveStatus.add(ScStatusConstant.ORDERE_SUSPEND);

        //OrganizationEntity org = user.getOrgId() == null ? null : this.repository.get(OrganizationEntity.class, user.getOrgId());
        for (Long id : idList) {
            ScProOrder scProOrder = this.getById(id);
            if (scProOrder == null) {
                continue;
            }
            Assert.isTrue(receiveStatus.contains(scProOrder.getStatus()), String.format("编号为%s的订单已不是办理中或已暂缓的状态！", scProOrder.getOrderBusinessNo()));
            Assert.isTrue(scProOrder.getFlowUserId().equals(user.getId()), String.format("编号为%s的订单流程人员非当前登陆人，无法进行操作！", scProOrder.getOrderBusinessNo()));
//            Assert.isTrue(!scProOrder.getProductId().equals(productId) || !scProOrder.getChannelId().equals(channelId), String.format("编号为%s的订单产品和渠道与订单当前产品和渠道相同！", scProOrder.getOrderBusinessNo()));
//            Assert.isTrue(scProOrder.getBtCode().equals(product.getType()), String.format("编号为%s的订单的业态与更换产品的业态不同！", scProOrder.getOrderBusinessNo()));
//
//            scProOrder.setProductId(productId); //产品
            scProOrder.setChannelId(channelId); //渠道
            scProOrder.setSubBranch(subBranch == null ? scProOrder.getSubBranch() : subBranch); //支行
            DataWrap.updateWraps(scProOrder); //更新操作人信息
            this.repository.saveOrUpdate(scProOrder);
            //操作记录
            ScProFlowOperating scProFlowOperating = new ScProFlowOperating();
            scProFlowOperating.setOperationType(ScOperationConstant.OPERATION_CHANNEL_CHANGE); // "SCORDER_CZ_CODE6" //更换渠道
            scProFlowOperating.setProProductId(scProOrder.getId());
            scProFlowOperating.setProProductNo(scProOrder.getOrderBusinessNo());
            scProFlowOperating.setFlowUserId(scProOrder.getFlowUserId());
            scProFlowOperating.setFlowUserName(scProOrder.getFlowUserName());
            scProFlowOperating.setStatus(scProOrder.getStatus());
            scProFlowOperating.setOperation("更换渠道");
            DataWrap.saveWrap(scProFlowOperating);
            scProFlowOperating.setId(this.keyWorker.nextId());
            this.repository.save(scProFlowOperating);

            //同步备注到crm
            Map recordMap = new HashMap();
            recordMap.put("tableName", ScProOrder.TABLE_NAME);
            recordMap.put("tableId", scProOrder.getId());
            recordMap.put("cusId", scProOrder.getCustomerId());
            recordMap.put("recordType", RemarkOperationConstant.REMARK_CHANNEL_CHANGE);//备注类型
            recordMap.put("content", "更换渠道");//备注内容
            recordMap.put("operateUser", user.getId());//当前操作人id
            recordMap.put("ext3", scProOrder.getOrderBusinessNo()); //生产子订单编号
            customerRecordService.saveCustomerRecord(recordMap);//写入crm
        }


    }

    /**
     * 拒收
     *
     * @param ids
     */
    public void update_refuseReceive(String ids) {
        Assert.hasText(ids, "订单ID不能为空！");
        User user = SessionManager.getCurrentUser();
        Assert.notNull(user, "当前用户获取失败，请刷新重新登录！");
        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.replaceAll(" ", "").split(",");
        for (String t : idArr) {
            idList.add(Long.valueOf(t));
        }
        Assert.isTrue(idList.size() > 0, "订单ID数据错误");
        OrganizationEntity org = user.getOrgId() == null ? null : this.repository.get(OrganizationEntity.class, user.getOrgId());
        Set<String> receiveStatus = new HashSet<>(); //待接收
        receiveStatus.add(ScStatusConstant.SWITCH_WAITING);
        for (Long id : idList) {
            ScProOrder scProOrder = this.getById(id);
            if (scProOrder == null) {
                continue;
            }
            waitAllocationService.updateUserSetting(scProOrder, "1"); //减1
            Assert.isTrue(receiveStatus.contains(scProOrder.getStatus()), String.format("编号为%s的订单不是转单待接收的状态！", scProOrder.getOrderBusinessNo()));
            Assert.isTrue(scProOrder.getWaitingReceiverId().equals(user.getId()), String.format("编号为%s的订单代收人员非当前登陆人，无法进行操作！", scProOrder.getOrderBusinessNo()));
            scProOrder.setStatus(ScStatusConstant.SWITCH_REFUSE); // 转单退回 SCORDER_STATUS12
            waitAllocationService.updateUserSetting(scProOrder, "2"); //加1
            DataWrap.updateWraps(scProOrder); //更新操作人信息
            this.repository.saveOrUpdate(scProOrder);
            //操作记录
            ScProFlowOperating scProFlowOperating = new ScProFlowOperating();
            scProFlowOperating.setOperationType(ScOperationConstant.OPERATION_SWITCH_RETURN); // "SCORDER_CZ_CODE5" //转单退回
            scProFlowOperating.setProProductId(scProOrder.getId());
            scProFlowOperating.setProProductNo(scProOrder.getOrderBusinessNo());
            scProFlowOperating.setFlowUserId(scProOrder.getFlowUserId());
            scProFlowOperating.setFlowUserName(scProOrder.getFlowUserName());
            scProFlowOperating.setStatus(scProOrder.getStatus());
            scProFlowOperating.setOperation("转单退回");
            DataWrap.saveWrap(scProFlowOperating);
            scProFlowOperating.setId(this.keyWorker.nextId());
            this.repository.save(scProFlowOperating);

            //同步备注到crm
            Map recordMap = new HashMap();
            recordMap.put("tableName", ScProOrder.TABLE_NAME);
            recordMap.put("tableId", scProOrder.getId());
            recordMap.put("cusId", scProOrder.getCustomerId());
            recordMap.put("recordType", RemarkOperationConstant.REMARK_SWITCH_RETURN);//备注类型
            recordMap.put("content", "转单退回");//备注内容
            recordMap.put("operateUser", user.getId());//当前操作人id
            recordMap.put("ext3", scProOrder.getOrderBusinessNo()); //生产子订单编号
            customerRecordService.saveCustomerRecord(recordMap);//写入crm

            //发送短信给流程
            this.sendSmsMsgToUser(scProOrder.getFlowUserId(), MsgCodeConstant.SC_ZDTH_MSG, scProOrder.getOrderBusinessNo());
        }


    }

    /**
     * 废单
     *
     * @param ids
     * @param reasonCode
     * @param reason
     */
    public void update_abolishScProOrder(String ids, String reasonCode, String reasonName, String reason) {
        Assert.hasText(ids, "订单ID不能为空！");
        Assert.hasText(reasonCode, "废单原因不能为空！");
        User user = SessionManager.getCurrentUser();
        Assert.notNull(user, "当前用户获取失败，请刷新重新登录！");
        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.replaceAll(" ", "").split(",");
        for (String t : idArr) {
            idList.add(Long.valueOf(t));
        }
        Assert.isTrue(idList.size() > 0, "订单ID数据错误");
        if ("FD_YY_CODE_OTHER".equals(reasonCode)) {
            Assert.hasText(reason, "废单原因为其他时，备注不能为空！");
        }
        Set<String> receiveStatus = new HashSet<>();
        receiveStatus.add(ScStatusConstant.ABANDON_AUDIT); //废单审核中
        receiveStatus.add(ScStatusConstant.ORDER_ANANDON); //已废单
        receiveStatus.add(ScStatusConstant.ORDER_COMPLETE); //已成单
        receiveStatus.add(ScStatusConstant.ORDER_RETURENED); //已退单


        OrganizationEntity org = user.getOrgId() == null ? null : this.repository.get(OrganizationEntity.class, user.getOrgId());
        for (Long id : idList) {
            ScProOrder scProOrder = this.getById(id);
            if (scProOrder == null) {
                continue;
            }
            Assert.isTrue(!receiveStatus.contains(scProOrder.getStatus()), String.format("编号为%s的订单无法进行废单！", scProOrder.getOrderBusinessNo()));
            Assert.isTrue(scProOrder.getFlowUserId().equals(user.getId()), String.format("编号为%s的订单流程人员非当前登陆人，无法进行废单！", scProOrder.getOrderBusinessNo()));
            if (!ScStatusConstant.RECEIVE_WAITING.equals(scProOrder.getStatus())) { //非待接收的订单 暂停更新 超期状态
                ScProOrderTimeState state = this.repository.get(ScProOrderTimeState.class, scProOrder.getId());
                if (state != null) {
                    this.scProOrderTimeStateService.update_suspendScProOrderTime(scProOrder.getId());
                }
            }
            scProOrder.setStatus(ScStatusConstant.ABANDON_AUDIT); //  "SCORDER_STATUS07"  // 废单审核中
            scProOrder.setNotes(reason);
            Assert.notNull(scProOrder.getFlowUserId(), "没有查询到该流程人员!");
            Assert.notNull(scProOrder.getFlowDeptId(), "没有查询到该流程人员的部门信息!");
            /*-----废单获取流程主管审核人信息-----*/
            scProOrder.setAuditStatus(1);  //流程主管审核
            Map map = abolishService.auditPerson(user.getOrgId(), 1);
            Assert.notNull(map, "该流程人员部门没有流程主管!");
            scProOrder.setAuditorId(Long.valueOf(String.valueOf(map.get("id"))));
            scProOrder.setAuditorName(String.valueOf(map.get("name")));
            DataWrap.updateWraps(scProOrder); //更新操作人信息
            User receiverUser = chargeBackService.queryAuditUser(scProOrder.getAuditorId());//查找推送信息接收人

            //操作记录
            ScProFlowOperating scProFlowOperating = new ScProFlowOperating();
            scProFlowOperating.setOperationType(ScOperationConstant.OPERATION_ABANDON_APPLY); // "SCORDER_CZ_CODE4" //申请废单
            scProFlowOperating.setProProductId(scProOrder.getId());
            scProFlowOperating.setProProductNo(scProOrder.getOrderBusinessNo());
            scProFlowOperating.setFlowUserId(scProOrder.getFlowUserId());
            scProFlowOperating.setFlowUserName(scProOrder.getFlowUserName());
            scProFlowOperating.setStatus(scProOrder.getStatus());
            scProFlowOperating.setRemark(reasonCode);
            scProFlowOperating.setRemarkInfo(reason);
            scProFlowOperating.setOperation("申请废单");
            DataWrap.saveWrap(scProFlowOperating);
            scProFlowOperating.setId(this.keyWorker.nextId());
            scProOrder.setFlowLatestOperationId(scProFlowOperating.getId());
            scProFlowOperating.setReturnOrAbandonTime(scProFlowOperating.getCreateTime()); //废单时间
            scProFlowOperating.setReturnOrAbandonRemark(reason); //废单原因
            this.repository.save(scProFlowOperating);
            this.repository.saveOrUpdate(scProOrder);
            waitAllocationService.updateUserSetting(scProOrder, "1");//废单减1
            String[] vals = new String[1];
            vals[0] = String.valueOf(scProOrder.getOrderBusinessNo());
            String tempCode = MsgCodeConstant.SC_DSH_MSG; // "SC_DSH_MSG";
            //String tem = "订单{0}需要审核，请及时查看";
            messageService.sendMessageReady(receiverUser, user, vals, tempCode);//消息提醒
            //同步备注到crm
            Map recordMap = new HashMap();
            recordMap.put("tableName", ScProOrder.TABLE_NAME);
            recordMap.put("tableId", scProOrder.getId());
            recordMap.put("cusId", scProOrder.getCustomerId());
            recordMap.put("recordType", RemarkOperationConstant.REMARK_ABANDON_APPLY);//备注类型
            recordMap.put("content", reason);//备注内容
            recordMap.put("operateUser", user.getId());//当前操作人id
            recordMap.put("ext3", scProOrder.getOrderBusinessNo()); //生产子订单编号
            customerRecordService.saveCustomerRecord(recordMap);//写入crm
        }
    }

    /**
     * 判断生产订单是否已退单
     *
     * @param id 子订单id
     * @return
     */
    public boolean queryProOrderStatus(Long id) {
        boolean type = false;
        if (null == id) {
            throw new BizException("生产订单ID不能为空！", 10005);
        }
        ScProOrder scProOrder = this.repository.get(ScProOrder.class, id);
        if (scProOrder != null) {
            if (scProOrder.getStatus().equals(ScStatusConstant.ORDER_RETURENED)) {  //已退单
                type = true;
            }
        } else {
            throw new BizException("没有查询到生产订单", 10005);
        }
        return type;
    }

    /**
     * 通过子订单编号查询
     *
     * @param orderNo
     * @return
     */
    public ScProOrder getByOrderBusinessNo(String orderNo) {
        return StringUtils.isEmpty(orderNo) ? null : (ScProOrder) this.repository.getSession()
                .createCriteria(ScProOrder.class)
                .add(Restrictions.eq("orderBusinessNo", orderNo)).setMaxResults(1).setFirstResult(0).uniqueResult();
    }

    /**
     * 查询异常订单
     *
     * @param map
     * @return
     */
    public List<Map> listExceptionOrder(Map map) {
        return this.scProOrderDao.listExceptionOrder(map);
    }

    /**
     * 查询异常订单
     *
     * @param map
     * @return
     */
    public Integer countExceptionOrder(Map map) {
        return this.scProOrderDao.countExceptionOrder(map);
    }


    /**
     * 直接转交订单
     *
     * @param ids
     * @param receiverId
     */
    public void update_transferOrder(String ids, Long receiverId) {
        Assert.hasText(ids, "订单ID不能为空！");
        Assert.notNull(receiverId, "接收人不能为空！");
        User user = SessionManager.getCurrentUser();
        Assert.notNull(user, "当前用户获取失败，请刷新重新登录！");
        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.replaceAll(" ", "").split(",");
        for (String t : idArr) {
            idList.add(Long.valueOf(t));
        }
        Assert.isTrue(idList.size() > 0, "订单ID数据错误");
        User receiver = this.repository.get(User.class, receiverId);
        Assert.notNull(receiver, "未能查询查询到接收人！");
        OrganizationEntity receiverOrg = receiver.getOrgId() == null ? null : this.repository.get(OrganizationEntity.class, receiver.getOrgId());
        Assert.notNull(receiverOrg, "此接收人没有查询到部门！");

        Assert.isTrue(User.LOCK_LOCKED != receiver.getLocked(), "此接收人已被锁定！");
        Assert.isTrue(User.LOCK_TURNOVER != receiver.getLocked(), "此接收人已离职！");
        List<ScProOrder> scProOrderList = this.repository.getSession().createCriteria(ScProOrder.class).add(Restrictions.in("id", idList)).list();

        for (ScProOrder scProOrder : scProOrderList) {
            //操作记录
            ScProFlowOperating scProFlowOperating = new ScProFlowOperating();
            scProFlowOperating.setProProductId(scProOrder.getId());
            scProFlowOperating.setProProductNo(scProOrder.getOrderBusinessNo());
            scProFlowOperating.setFlowUserId(scProOrder.getFlowUserId());
            scProFlowOperating.setFlowUserName(scProOrder.getFlowUserName());
            scProFlowOperating.setStatus(scProOrder.getStatus());
            scProFlowOperating.setOperationType(ScOperationConstant.OPERATION_ORDER_TRANSFER); // "SCORDER_CZ_CODE19" //移交
            scProFlowOperating.setOperation("移交");
            scProFlowOperating.setRemarkInfo(String.format("生产订单（%s）移交给%s(%s)", scProOrder.getOrderBusinessNo(), receiver.getName(), receiverOrg.getName()));
            DataWrap.saveWrap(scProFlowOperating);
            scProFlowOperating.setId(this.keyWorker.nextId());

            //修改接收人
            if (ScStatusConstant.SWITCH_WAITING.equals(scProOrder.getStatus())) {
                waitAllocationService.updateUserSetting(scProOrder, "1");
                scProOrder.setWaitingReceiverId(receiverId);
                scProOrder.setWaitingReceiverName(String.format("%s(%s)", receiver.getName(), receiverOrg.getName()));
                scProOrder.setWaitingReceiverOrgId(receiverOrg.getId());
                scProOrder.setWaitingReceiverOrgName(receiverOrg.getName());
                scProFlowOperating.setFlowUserId(scProOrder.getWaitingReceiverId());
                scProFlowOperating.setFlowUserName(scProOrder.getWaitingReceiverName());
                waitAllocationService.updateUserSetting(scProOrder, "2");
            } else { // 修改流程人员
                waitAllocationService.updateUserSetting(scProOrder, "1");
                scProOrder.setFlowUserId(receiverId);
                scProOrder.setFlowUserName(String.format("%s(%s)", receiver.getName(), receiverOrg.getName()));
                scProOrder.setFlowDeptId(receiverOrg.getId());
                scProOrder.setWaitingReceiverOrgName(receiverOrg.getName());
                waitAllocationService.updateUserSetting(scProOrder, "2");
            }
            scProOrder.setFlowLatestOperationId(scProFlowOperating.getId()); // 最新操作
            this.repository.saveOrUpdate(scProOrder);
            this.repository.save(scProFlowOperating);
        }
    }


    /**
     * 子订单是否含有资金业务
     *
     * @param proOrderId
     * @param ignoreScProOrderId
     * @return 1: 是  2 否
     */
    public Integer getIsbelongrisk(Long proOrderId, Long ignoreScProOrderId) {
        Long sum = (Long) this.repository.getSession().createCriteria(ScProOrder.class).setProjection(Projections.rowCount())
                .add(Restrictions.eq("proOrderId", proOrderId))
                .add(Restrictions.ne("id", ignoreScProOrderId))
                .add(Restrictions.like("btCode", BusCodeConstant.BUS_YT_ZJYW, MatchMode.ANYWHERE)).uniqueResult();
        return sum.intValue() > 0 ? 1 : 2;

    }


    /**
     * 更新是否含有资金业务 字段
     *
     * @param proOrderId
     * @param isbelongrisk       1: 是  2 否
     * @param ignoreScProOrderId
     */
    public void updateIsbelongrisk(Long proOrderId, Integer isbelongrisk, Long ignoreScProOrderId) {
        Query query = this.repository.getSession().createQuery("update " + ScProOrder.class.getName() + " e  set e.isbelongrisk = :isbelongrisk where e.proOrderId = :proOrderId  and e.id != :ignoreScProOrderId");
        query.setParameter("isbelongrisk", isbelongrisk);
        query.setParameter("proOrderId", proOrderId);
        query.setParameter("ignoreScProOrderId", ignoreScProOrderId);
        query.executeUpdate();
    }

    /**
     * 发送短信给人员
     *
     * @param receiverId
     * @param msgTempCode
     * @param OrderBusinessNo
     */
    public void sendSmsMsgToUser(Long receiverId, String msgTempCode, String OrderBusinessNo) {
        if (receiverId == null || StringUtils.isEmpty(msgTempCode) || StringUtils.isEmpty(OrderBusinessNo)) {
            return;
        }
        MessageTemplate msgTemplate = this.messageTemplateDao.getMessageTemplateByCode(msgTempCode);
        if (msgTemplate == null || StringUtils.isEmpty(msgTemplate.getContent())) {
            return;
        }
        String msgTemp = msgTemplate.getContent().replaceAll("<[.[^>]]*>", "").replaceAll(" ", "");
        User user = this.userDao.find4Id(receiverId);
        if (user == null || StringUtils.isEmpty(user.getPhone())) {
            return;
        }
        this.smaBaiwu.sendMsg(user.getPhone(), msgTemp.replace("{0}", OrderBusinessNo));
    }


    /**
     * 设置 订单状态
     *
     * @param scProOrder
     */
    private void setScOrderStatus(ScProOrder scProOrder) {
        if (scProOrder == null) {
            return;
        }
        // 资金业务 直接待接收
        if (BusCodeConstant.BUS_YT_ZJYW.equals(scProOrder.getBtCode())) {
            scProOrder.setStatus(ScStatusConstant.RECEIVE_WAITING);
            scProOrder.setOriginCode(OriginCodeSource.SC_ORIGINCODE_BUSINESS); //默认订单来源
            return;
        }
        ScAutoAllotOrgConfig scAutoAllotOrgConfig = (ScAutoAllotOrgConfig) this.repository.getSession()
                .createCriteria(ScAutoAllotOrgConfig.class)
                .add(Restrictions.eq("btCode", scProOrder.getBtCode()))
                .add(Restrictions.eq("organizationId", scProOrder.getOrganizationId()))
                .setMaxResults(1).uniqueResult();
        if (scAutoAllotOrgConfig == null || scAutoAllotOrgConfig.getDebugCall() == null || 1 != scAutoAllotOrgConfig.getDebugCall().intValue()) {
            scProOrder.setStatus(ScStatusConstant.RECEIVE_WAITING);
            scProOrder.setOriginCode(OriginCodeSource.SC_ORIGINCODE_BUSINESS); //默认订单来源
            return;
        }

        // 待分配
        scProOrder.setStatus(ScStatusConstant.WAIT_ALLOCATION);

    }

}
